#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <cstdio>
#include <cstdio>
#include <cstring>
#include <sys/types.h>
#include <sys/syscall.h>
using namespace std;
#include "lock.hpp"

// 模拟死锁问题
pthread_mutex_t mutexA = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutexB = PTHREAD_MUTEX_INITIALIZER;

void *startRountine1(void *args)
{
    while (true)
    {
        pthread_mutex_lock(&mutexA);
        pthread_mutex_lock(&mutexB);
        cout << "我是线程1, tid:" << pthread_self() << endl;
        pthread_mutex_unlock(&mutexA);
        pthread_mutex_unlock(&mutexB);
    }
}

void *startRountine2(void *args)
{
    while (true)
    {
        // pthread_mutex_lock(&mutexA);
        // pthread_mutex_lock(&mutexB);
        pthread_mutex_lock(&mutexB);
        pthread_mutex_lock(&mutexA);
        cout << "我是线程2, tid:" << pthread_self() << endl;
        pthread_mutex_unlock(&mutexB);
        pthread_mutex_unlock(&mutexA);
    }
}

int main()
{
    pthread_t t1, t2;

    pthread_create(&t1, nullptr, startRountine1, nullptr);
    pthread_create(&t2, nullptr, startRountine2, nullptr);

    pthread_join(t1, nullptr);
    pthread_join(t2, nullptr);
    return 0;
}

// int tickets = 1000;
// Mutex mutex;

// // 函数本质是一个代码块,会被多个线程同时调用执行，该函数被重复进入 - 被重入了
// bool getTickets()
// {
//     bool ret = false; // 函数局部变量，在栈上保持，线程具有独立的栈结构，每个线程各自一份
//     LockGuard lockguard(&mutex); // 局部对象的生命周期是随代码块的,函数调用完成之后自动解锁
//     if (tickets > 0)
//     {
//         usleep(1000);
//         cout << "thread:" << pthread_self() << " 抢到了票，票的编号：" << tickets << endl;
//         tickets--;
//         ret = true;
//     }
//     return ret;
// }

// void *startRountine(void *args)
// {
//     const char *name = static_cast<const char *>(args);
//     while (true)
//     {
//         if (!getTickets())
//             break;
//         cout << name << " get tickets success!" << endl;
//         usleep(100);
//     }
// }

// int main()
// {
//     // pthread_t t1,t2,t3,t4;
//     // {
//     //     // 临界资源
//     //     LockGuard LockGuard(&mutex);
//     //     cnt++;
//     //     // ...
//     //     // ...
//     // }

//     pthread_t tid1;
//     pthread_t tid2;
//     pthread_t tid3;
//     pthread_t tid4;

//     pthread_create(&tid1, nullptr, startRountine, (void *)"thread 1");
//     pthread_create(&tid2, nullptr, startRountine, (void *)"thread 2");
//     pthread_create(&tid3, nullptr, startRountine, (void *)"thread 3");
//     pthread_create(&tid4, nullptr, startRountine, (void *)"thread 4");

//     pthread_join(tid1, nullptr);
//     pthread_join(tid2, nullptr);
//     pthread_join(tid3, nullptr);
//     pthread_join(tid4, nullptr);

//     return 0;
// }

// int tickets = 10000; // 临界资源，可能会因为共同访问，可能会造成数据不一致问题
// //pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;

// #define NAMESIZE 64
// typedef struct threadData
// {
//     char name[NAMESIZE];
//     pthread_mutex_t *mutexp;
// }threadDate;

// void *getTickets(void *args)
// {
//     // pthread_mutex_t *mutex_p=static_cast<pthread_mutex_t *>(args);
//     threadData *td=static_cast<threadData *>(args);
//     while (true)
//     {
//         pthread_mutex_lock(td->mutexp);
//         if (tickets > 0)
//         {
//             cout << td->name << " 抢到了票，票的编号：" << tickets << endl;
//             tickets--;
//             pthread_mutex_unlock(td->mutexp);

//             usleep(500);
//         }
//         else
//         {
//             cout << td->name << " 没有抢到票，票已经售完了..." << endl;
//             pthread_mutex_unlock(td->mutexp);
//             break;
//         }
//     }
//     return nullptr;
// }

// int main()
// {
//     static pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;

//     pthread_t tid1;
//     pthread_t tid2;
//     pthread_t tid3;
//     pthread_t tid4;

//     threadData *td=new threadData();
//     strcpy(td->name,"thread 1");
//     td->mutexp=&mutex;

//     pthread_create(&tid1, nullptr, getTickets, td);
//     // pthread_create(&tid2, nullptr, getTickets, (void *)&mutex);
//     // pthread_create(&tid3, nullptr, getTickets, (void *)&mutex);
//     // pthread_create(&tid4, nullptr, getTickets, (void *)&mutex);

//     pthread_join(tid1, nullptr);
//     // pthread_join(tid2, nullptr);
//     // pthread_join(tid3, nullptr);
//     // pthread_join(tid4, nullptr);

//     pthread_mutex_destroy(&mutex);
//     delete td;
//     return 0;
// }

// 临界资源
// 票数计数器
// int tickets = 10000; // 临界资源，可能会因为共同访问，可能会造成数据不一致问题
// pthread_mutex_t mutex;

// void *getTickets(void *args)
// {
//     const char *name = static_cast<const char *>(args);
//     while (true)
//     {
//         // 临界区,只需要对临界区加锁，而且加锁的粒度越细越好
//         // 加锁的本质是让线程执行临界区代码串行化
//         // 锁保护的是临界区，任何线程执行临界区代码访问访问临界资源，都必须先申请锁，前提是必须先看到锁！
//         // 这把锁，本身就是临界资源？？？锁的设计者早就想到了！
//         // pthread_mutex_lock:竞争和申请锁的过程，就是原子的！
//         pthread_mutex_lock(&mutex);
//         if (tickets > 0)
//         {
//             // usleep(1000); // 演示票数抢到负数
//             cout << name << " 抢到了票，票的编号：" << tickets << endl;
//             tickets--;
//             pthread_mutex_unlock(&mutex);
//         }
//         else
//         {
//             cout << name << " 没有抢到票，票已经售完了..." << endl;
//             pthread_mutex_unlock(&mutex);
//             break;
//         }
//     }
//     return nullptr;
// }

// int main()
// {
//     pthread_mutex_init(&mutex, nullptr);
//     pthread_t tid1;
//     pthread_t tid2;
//     pthread_t tid3;
//     pthread_t tid4;
//     pthread_create(&tid1, nullptr, getTickets, (void *)"thread 1");
//     pthread_create(&tid2, nullptr, getTickets, (void *)"thread 2");
//     pthread_create(&tid3, nullptr, getTickets, (void *)"thread 3");
//     pthread_create(&tid4, nullptr, getTickets, (void *)"thread 4");

//     pthread_join(tid1, nullptr);
//     pthread_join(tid2, nullptr);
//     pthread_join(tid3, nullptr);
//     pthread_join(tid4, nullptr);

//     pthread_mutex_destroy(&mutex);

//     return 0;
// }
